﻿#region Usings

using System;
using System.Windows;
using System.Windows.Interactivity;
using SilverBox.Physics;

#endregion

namespace SilverBox.Behaviors
{
    public class CollideTrigger : TriggerBase<FrameworkElement>
    {
        public static readonly DependencyProperty MinForceProperty = DependencyProperty.Register("MinForce",
                                                                                                 typeof (double),
                                                                                                 typeof (CollideTrigger),
                                                                                                 new PropertyMetadata(
                                                                                                     0.0));

        public static readonly DependencyProperty TypeProperty = DependencyProperty.Register("Type", typeof (Type),
                                                                                             typeof (CollideTrigger),
                                                                                             new PropertyMetadata(null));

        private Entity entity;

        public double MinForce
        {
            get { return (double) GetValue(MinForceProperty); }
            set { SetValue(MinForceProperty, value); }
        }


        public Type Type
        {
            get { return (Type) GetValue(TypeProperty); }
            set { SetValue(TypeProperty, value); }
        }

        protected override void OnAttached()
        {
            base.OnAttached();

            entity = GetEntity(AssociatedObject);

            if (entity == null)
            {
                Dispatcher.BeginInvoke(delegate
                                           {
                                               entity = GetEntity(AssociatedObject);
                                               Attach(entity);
                                           });
            }
            else
                Attach(entity);
        }

        protected override void OnDetaching()
        {
            base.OnDetaching();

            if (entity != null)
                Detach(entity);
        }

        private Entity GetEntity(FrameworkElement element)
        {
            return Entity.GetElementEntity(element);
        }

        private void Attach(Entity entity)
        {
            entity.Collide += HandleCollide;
        }

        private void Detach(Entity entity)
        {
            entity.Collide -= HandleCollide;
        }

        private void HandleCollide(object sender, CollideEventArgs e)
        {
            if (e.ContactPoint.Velocity.Length() > MinForce)
            {
                if (Type == null || Type.IsAssignableFrom(e.Other.GetType()))
                    InvokeActions(e);
            }
        }
    }
}